#![allow(dead_code)]

use away_db::{
    entity::*,
    trader_repository::{stock_order_rep::AddOrder, *},
};
use sea_orm::{DbConn, TransactionTrait};

/// 模拟交易
/// status  -2撤销、-1失败、0委托、1成交
/// 1、挂单（委托订单）
/// 买入：校验可用余额，冻结交易金额
/// 卖出：校验可用股数，冻结交易股数
///
/// 2、成交 (委托订单 --> 交易成功)【监听行情进行事件触发】
/// 买入：扣除冻结交易余额，添加持仓股数
/// 卖出：扣除冻结交易股数，添加可用余额
///
/// 3、休市(委托订单 --> 交易失败)
/// 买入：扣除冻结交易金额，添加可用余额
/// 卖出：扣除冻结交易股数，添加可用股数

/// 撤单
pub async fn cancel(db: &DbConn, uid: i32, oid: i32) -> Result<bool, String> {
    let order_res = stock_order_rep::get_by_id(db, uid, oid).await;
    println!("{:?}", order_res);
    if let Ok(Some(order)) = order_res {
        let txn = db.begin().await.unwrap();
        let res = trade_failed(db, &order).await;
        if res.is_err() {
            return Err("撤单失败".to_owned());
        }
        let cancel_res = stock_order_rep::update_status(db, oid, uid, -2).await;
        if cancel_res.is_err() {
            return Err("撤单失败".to_owned());
        }
        // 提交事务
        if txn.commit().await.is_err() {
            return Err("交易失败:tran".to_owned());
        }
        return Ok(true);
    }
    Err("撤单单失败:none".to_owned())
}

/// 闭市任务  
pub async fn trade_end(db: &DbConn) {
    let res = stock_wallet_rep::update_number_by_trade_newday(db).await;
    let orders = stock_order_rep::get_by_status(db, 0).await.unwrap();
    for item in orders {
        _ = trade_failed(db, &item).await;
    }
    println!("{:?}", res);
}

/// 开市任务  
pub async fn trade_start(db: &DbConn, stock_code: &str, price: f64) {
    println!("股票代码：{}  价格：{}", stock_code, price);
    let orders = stock_order_rep::get_by_stockcode(db, stock_code, price)
        .await
        .unwrap();
    for item in orders {
        _ = trade_success(db, &item).await;
    }
}

/// 交易成功
async fn trade_success(db: &DbConn, order: &stock_order::Model) -> Result<bool, String> {
    let txn = db.begin().await.unwrap();

    let uid = order.uid;
    let number = order.trading_number;
    let price: f64 = order.price.try_into().unwrap();
    let money = number as f64 * price;

    // 买入：扣除冻结交易余额，添加持仓股数
    if number > 0 {
        let trade_res = stock_user_rep::update_money_by_trade_buy(db, uid, -money).await;
        if trade_res.is_err() {
            return Err("扣除冻结余额失败".to_owned());
        }

        let trade_res = stock_wallet_rep::update_number_by_trade_success(
            db,
            uid,
            order.stock_code.clone(),
            number,
        )
        .await;
        if trade_res.is_err() {
            return Err("添加持仓股数失败".to_owned());
        }
    }

    // 卖出：扣除冻结交易股数，添加可用余额
    if number < 0 {
        let trade_res = stock_user_rep::update_money_by_transfer(db, uid, -money).await;
        if trade_res.is_err() {
            return Err("添加余额失败".to_owned());
        }

        let trade_res = stock_wallet_rep::update_number_by_trade_success(
            db,
            uid,
            order.stock_code.clone(),
            number,
        )
        .await;
        if trade_res.is_err() {
            return Err("扣除持仓股数失败".to_owned());
        }
    }

    // 更新订单状态
    let order_res = stock_order_rep::update_status(db, order.id, uid, 1).await;
    if order_res.is_err() {
        return Err("更新订单状态失败".to_owned());
    }

    // 提交事务
    if txn.commit().await.is_err() {
        return Err("交易失败:tran".to_owned());
    }
    println!("交易成功：{:?}", order);
    Ok(true)
}

/// 交易失败、撤单
async fn trade_failed(db: &DbConn, order: &stock_order::Model) -> Result<bool, String> {
    let txn = db.begin().await.unwrap();

    let uid = order.uid;
    let number = order.trading_number;
    let price: f64 = order.price.try_into().unwrap();
    let money = number as f64 * price;

    // 买入：扣除冻结交易金额，添加可用余额
    if number > 0 {
        let res = stock_user_rep::update_money_by_trade(db, uid, -money).await;
        if res.is_err() {
            return Err("解除冻结金额失败".to_owned());
        }
    }

    // 卖出：扣除冻结交易股数，添加可用股数
    if number < 0 {
        let res = stock_wallet_rep::update_number_by_trade(
            db,
            uid,
            order.stock_code.clone(),
            number.abs(),
        )
        .await;
        if res.is_err() {
            return Err("解除冻结股数失败".to_owned());
        }
    }

    // 更新订单状态
    let order_res = stock_order_rep::update_status(db, order.id, uid, -1).await;
    if order_res.is_err() {
        return Err("更新订单状态失败".to_owned());
    }
    // 提交事务
    if txn.commit().await.is_err() {
        return Err("交易失败:tran".to_owned());
    }
    println!("撤单成功{:?}", order);
    Ok(true)
}

/// trading_number 正数为买入，负数为卖出
pub async fn buy_or_sell(db: &DbConn, dto: AddOrder) -> Result<bool, String> {
    let txn = db.begin().await.unwrap();

    // 校验买入卖出
    let can_sell_res = is_can_sell(db, &dto).await;
    if can_sell_res.is_err() {
        return can_sell_res;
    }
    let can_buy_res = is_can_buy(db, &dto).await;
    if can_buy_res.is_err() {
        return can_buy_res;
    }

    // 添加交易撮合任务
    let stock_code = &dto.stock_code;
    let job_res = stock_trade_job_rep::add(db, stock_code).await;
    if job_res.is_err() {
        return job_res;
    }

    let res = stock_order_rep::add(db, dto).await;
    if res.is_err() {
        return Err("挂单失败:order_add".to_owned());
    }
    if txn.commit().await.is_err() {
        return Err("挂单失败:tran".to_owned());
    }
    Ok(true)
}

/// 校验可抛售的股数
async fn is_can_sell(db: &DbConn, dto: &AddOrder) -> Result<bool, String> {
    if dto.trading_number > 0 {
        return Ok(true);
    }

    let wallet_res =
        stock_wallet_rep::get_by_stockcode(db, dto.uid, dto.stock_code.to_string()).await;

    if wallet_res.is_err() {
        return Err("查询出错".to_owned());
    }
    let wallet_data = wallet_res.unwrap();
    if wallet_data.is_none() {
        return Err("超过可用持仓数量".to_owned());
    }
    let wallet = wallet_data.unwrap();
    if wallet.usable_number + dto.trading_number < 0 {
        return Err("超过可用持仓数量".to_owned());
    }

    // 卖出冻结股数
    let trade_res = stock_wallet_rep::update_number_by_trade(
        db,
        dto.uid,
        dto.stock_code.clone(),
        dto.trading_number,
    )
    .await;

    match trade_res {
        Ok(_) => Ok(true),
        Err(_) => Err("交易失败：user_error".to_owned()),
    }
}

/// 校验可购买股数余额
async fn is_can_buy(db: &DbConn, dto: &AddOrder) -> Result<bool, String> {
    if dto.trading_number < 0 {
        return Ok(true);
    }

    let user_res = stock_user_rep::get_by_id(db, dto.uid).await;
    if user_res.is_err() {
        return Err("查询出错".to_owned());
    }

    let user_data = user_res.unwrap();
    if user_data.is_none() {
        return Err("用户不存在".to_owned());
    }
    let user = user_data.unwrap();
    let money = dto.trading_number as f64 * dto.price;
    let usable_money: f64 = user.usable_money.try_into().unwrap();

    if usable_money - money < 0.0 {
        return Err("可用余额不足".to_owned());
    }

    //买入冻结金额
    let trade_res = stock_user_rep::update_money_by_trade(db, dto.uid, money).await;

    match trade_res {
        Ok(_) => Ok(true),
        Err(_) => Err("交易失败：user_error".to_owned()),
    }
}
